home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / edit / aaem95ma.zip / DISPLAY.CC < prev    next >
C/C++ Source or Header  |  1995-02-24  |  14KB  |  246 lines

  1. /* This file is DISPLAY.CC */
  2. #include "em.h"
  3. char*offscreen="cursor is one column off screen";
  4. static byte current_buffer=1;
  5. /*----- if this line should have its eol char printed */
  6. int line::showeol(){if(no_cr()) return LF; if(!n) return CR;
  7. reg char C=s[n-1]; if(C!=' ') if(C!='I'-64) if(C) if(C!='\377') if(C!=CR)
  8.   if(mark(this,n)!=B->col.Reg.beg) if(!next?:mark(next,0)!=B->col.Reg.end)
  9.   return 0;
  10. return CR;}
  11. /*-----*/
  12. void refreshscreen(){int i; buffer*BB=B; current_buffer=0;
  13. for(i=0;i<nwindows;i++)if((B=window[i])->nrows)if(i!=currentwindow)B->display();
  14. current_buffer=1; (B=window[currentwindow])->display(); B=BB;}
  15. /*-----*/
  16. void buffer::redraw_info() {int i; char cw[512];
  17.     pr(cw,"  AAEMACS: %s",name); if(bound.n) pa(cw," (%k)",&bound);
  18.     for(i=0;i<gp_Cols;i++) Sl[lastrow].sa[i]=sch(' ',Attrib(Magenta,White));
  19.     if(changed) cw[0]='*'; ::displayn(cw,lastrow,0,Magenta,White);
  20.     if(start.c) scr(lastrow,1)=17+256*(Red+16*White); Sl[lastrow].ok=1;}
  21. /*----- on ith row of screen. To (SL->nc-1)th col */ /* 9==tab */
  22. void line::display(int i){screenline *SL=&Sl[i];
  23. if(this==line0) {gp_clear(i); SL->ok=0; return;} if(!la()) if(SL->ok) return;
  24. char tt=B->tabtype,*S=s; byte C;
  25. int sheol=showeol(),j=0,k=0,spdue=0,geeup=B->start.c,whoa=gp_Cols+geeup;
  26. uns short at=gp_Attr<<8, *Screen=SL->sa-geeup, sc;
  27. OFFLEFT: if(!tt) j=k=geeup; if(j>=geeup) goto NEXTCHAR;
  28. if(spdue) {spdue--; C=' ';} else if(k<n) C=S[k++]; else goto EOL; /* get char */
  29. if(C==9) if(tt) spdue=sptotab(j); j++; goto OFFLEFT;
  30. NEXTCHAR: if(spdue) {spdue--; C=' ';} else if(k<n) C=S[k++]; /* get char */
  31. else {if(k>n ?: !sheol) goto EOL; C=sheol; k++;}
  32. if(j==whoa) {Screen[j-1]=sch(16,(gp_Attr&~15)|Red); goto EOL;}
  33. if(C==9)if(tt) {Screen[j]=(tt==1?' ':9)|at; spdue=sptotab(j);j++;goto NEXTCHAR;}
  34. Screen[j++]=C|at; goto NEXTCHAR;
  35. EOL: if(j<=geeup) {Screen[geeup]=(sheol?:CR)|at; j=geeup+1;}
  36. k=(SL->nc+geeup)<?whoa; sc=' '|at; while(k>j) Screen[--k]=sc; SL->nc=j;
  37. SL->ok=1; la(0);}
  38. /*-----*/
  39. void buffer::display(){reg int h,i,j; int k,l,m,n,p,u,v,w,N,P; char *T;
  40. line *L,*M; short attr; screenline*S; if(longlines) {dispfold(); return;}
  41. #define forwin(S,i) for(i=row1;S=Sl+i,i<lastrow;i++)
  42. if(this!=B) MOAN("BUG: tried to display non-current buffer"); if(!nrows) return;
  43. forwin(S,i) if(S->buf!=this) {S->ok=0; S->buf=this;}
  44. char redrawinfo=Sl[lastrow].buf!=this?:!Sl[lastrow].ok?:changed!=oldch;
  45. j=-1; L=start.r; forwin(S,i) {if((S->nl=L)==dot.r) j=i; if(!(L=L->next)) break;}
  46. if(j<0) {for(L=dot.r,i=(nrows-1)/2;i>0;i--,L=L->prev) if(!L->prev) break;
  47.      start.r=L; forwin(S,i) {if((S->nl=L)==dot.r) j=i; if(!(L=L->next)) break;}}
  48. for(i++;i<lastrow;i++) Sl[i].nl=line0; dot.r->dotty();
  49. cursor.c=i=dot.r->to_scrcolno(dot.c); cursor.r=j; k=start.c=startc;
  50. if(i<0?1:i>=gp_Cols) { /* move display to left or right? */
  51.     if(i!=gp_Cols?0:dot.c!=dot.r->n?0:!dot.r->showeol()) {
  52.     if(current_buffer) Moan=offscreen;}
  53.     else {forwin(S,i) S->ok=0; /* must redraw */
  54.     j=gp_Cols; dotcc=-1; dot.r->dotty(); k=dotcc+start.c;
  55.     startc=start.c=k<j ?0: (i=(k-j/4)/(j/2),i*(j/2)); cursor.c=k-start.c;}}
  56. forwin(S,i) if(L=S->l) L->sl=line_notshown;
  57. forwin(S,i) S->nl->sl=i; line0->sl=line_notshown; /*reset .sl's for new screen*/
  58. forwin(S,i) if(!S->ok ?1: S->l!=S->nl) {S->nc=gp_Cols; S->nl->la(1);}
  59. forwin(S,i) (S->l=S->nl)->display(i);
  60. if(L=col.Reg.beg.r) {h=Attrib(col.fg,col.bg);
  61.     u=L->to_scrcolno(col.Reg.beg.c)>?0;
  62.     for(M=0;L;L=L->next) if(L==col.Reg.end.r) {M=L; break;} L=col.Reg.beg.r;
  63.     if(M) do {m=L==M;
  64.     if((k=L->sl)!=line_notshown) {
  65.         Sl[k].ok=0; v=(m?L->to_scrcolno(col.Reg.end.c):Sl[k].nc)<?gp_Cols;
  66.         T=(char*)Sl[k].sa+1; for(i=u;i<v;i++) T[i<<1]=h;}
  67.     u=0; if(m) break;} while(L=L->next);
  68.     col.Reg.beg=mark(); col.Reg.end=mark();}
  69. Sl[lastrow].l=modeline; oldch=changed; emptydustbin();
  70. if(redrawinfo) redraw_info(); cursor.c<?=gp_Cols-1; gp_cursor(cursor);
  71. /*** if any change of window sizes, Sl[i].ok=0 on affected lines ***/
  72. /*** ditto for all lines of any buffer that I get rid of ***/ }
  73. /*----- on ith etseq row of screen. 9==tab. Returns next free screen lineno */
  74. int line::dispfold(int i) {if(i>=B->lastrow) return i; screenline *SL=Sl+i;
  75. int J,dc=B->dot.c<?B->dot.r->n; line*dr=B->dot.r;
  76. if(this==line0) {if(i>=B->row1) {gp_clear(i); SL->ok=0;} return i+1;} sl=i;
  77. if(!la()) if(i>=B->row1) if(SL->ok) if(SL->l==this) if(!SL->lp) if(this!=dr){
  78.     while(SL->l==this) SL++; return SL-Sl;} /* line unchanged & unmoved */
  79. byte C; char*S=s,tt=B->tabtype; uns short sc;
  80. int I=i,m,sheol=showeol(),N=sheol?n:n-1; /*** call dotty() first ***/
  81. uns short *Sc=screen+i*gp_Cols,*geeup=screen+B->row1*gp_Cols,*whoa=Sc+gp_Cols,
  82.   at=gp_Attr<<8; int j=0,k=0,spdue=0; if(Sc>=geeup) goto NEXTCHAR;
  83. OFFTOP:
  84. if(spdue){spdue--;C=' ';}else if(k>N)return I+1; else C=k==n?(k++,sheol):S[k++];
  85. if(C==9?tt:0) {sc=(tt==1?' ':9)|at; spdue=sptotab(j);} else sc=C|at; j++;Sc++;
  86. if(Sc>=whoa) if(k<=N) {I++; if(Sc>=geeup) goto RED; SL++; whoa+=gp_Cols; Sc+=2;}
  87. goto OFFTOP;
  88. NEXTCHAR: if(dr==this) if(dc==k) cursor=gp_cur(I,Sc-whoa+gp_Cols);
  89. if(spdue){spdue--;C=' ';}else if(k>N) goto EOL; else C=k==n?(k++,sheol):S[k++];
  90. if(C==9?tt:0) {*Sc++=sc=(tt==1?' ':9)|at; spdue=sptotab(j);} else *Sc++=sc=C|at;
  91. j++;
  92. if(Sc>=whoa) if(k<=N) {
  93.     sc=Sc[-1]; Sc[-1]=sch(16,(gp_Attr&~15)|Red); SL->nc=gp_Cols; SL->nc=gp_Cols;
  94.     SL->l=this; SL->lp=I-i; SL->lc=k-1; if(++I>=B->lastrow) return I;
  95. RED: if(dr==this) if(dc==k-1) cursor=gp_cur(I,Sc-whoa+1); SL++;
  96.     whoa+=gp_Cols; *Sc++=sch(17,(gp_Attr&~15)|Red); *Sc++=sc;}  goto NEXTCHAR;
  97. EOL: whoa=screen+(j=I*gp_Cols)+SL->nc; sc=' '|at; SL->nc=Sc-j-screen; SL->ok=1;
  98. la(0); SL->l=this; SL->lp=I-i; SL->lc=n; while(Sc<whoa) *Sc++=sc; return I+1;}
  99. /*----- screen location of char within line */
  100. int linewhere(mark M){int c,k,z; if(!M.r) return 0;
  101. z=M.r->showeol()?M.r->n:M.r->n-1; /* # chars in line (with eol if displayed) */
  102. c=M.r->to_tabexp(M.c<?M.r->n); /* char position in line as displayed */
  103. return !c ?0: c+2*((c-(M.c>=z?2:1))/(gp_Cols-2));}
  104. /*----- screen location of mark *//* relies on screen lines being consecutive */
  105. static int scrwhere(mark M,int defolt=0){int k;
  106. if(!M.r ?: M.r==line0 ?: (k=M.r->sl)==line_notshown) return defolt;
  107. return k*gp_Cols+linewhere(M);}
  108. /*----- how many parts in folded line (up to c, if c>=0) */
  109. int line::nparts(int c/*=-1*/) {return 1+linewhere(mark(this,c<0?n:c))/gp_Cols;}
  110. /*----- display buffer in fold-long-lines mode */
  111. void buffer::dispfold(int d/*=0*/){reg int h,i,j; int jj,k,l,m,n,p,u,v,w,N,P;
  112. char *T; line *L,*M; short attr; screenline*S; char fold=B->longlines;
  113. if(this!=B) MOAN("BUG: tried to display non-current buffer"); if(!nrows) return;
  114. for(i=row1;i<=lastrow;i++) if(Sl[i].buf!=this) {Sl[i].ok=0; Sl[i].buf=this;}
  115. char redrawinfo=!Sl[lastrow].ok?1:(changed!=oldch); start.c=startc; stback+=d;
  116. M=start.r; while(M->next?(j=stback-M->nparts())>=0:0) {M=M->next; stback=j;}
  117. while(stback<0?(L=M->prev):0) stback+=(M=L)->nparts(); stback>?=0; start.r=M;
  118. forwin(S,i) {if(L=S->l) L->sl=line_notshown; if(!S->ok) S->nc=gp_Cols;}
  119. L=start.r; i=row1-stback; S=Sl+i; cursor.r=cursor.c=255; dot.r->dotty();
  120. while(i<lastrow) {i=L->dispfold(i); L=L->next?:line0;}
  121. if(d) if(L==line0) {d=0; dot.r=text.prev; dot.c=0;} /* off end of buffer */
  122. if(d){i=row1+nrows/2; dot=mark(L=Sl[i].l,Sl[i].lc);dotcc=-1;L->dispfold(L->sl);}
  123. else {
  124.     if(refresh?:cursor.r==255) { /* dot not on screen */
  125.     forwin(S,i) {if(L=S->l) L->sl=line_notshown; S->ok=0; S->nc=gp_Cols;}
  126.     L=dot.r; j=L->nparts(dot.c<?L->n); i=row1+nrows/2-j+1; refresh=0;
  127.     while(L->prev?i>row1:0) i-=(L=L->prev)->nparts();
  128.     if(i>row1) {i=row1; L=B->text.next;} stback=row1-i; start=mark(L,0);
  129.     while(i<lastrow) {i=L->dispfold(i); L=L->next?:line0;}}}
  130. if(L=col.Reg.beg.r) {h=Attrib(col.fg,col.bg);
  131.     for(M=0;L;L=L->next) if(L==col.Reg.end.r) {M=L; break;} L=col.Reg.beg.r;
  132.     if(M) for(i=0;L;L=L->next,i++) {m=L==M;
  133.     if((k=L->sl)!=line_notshown) {S=Sl+k;
  134.         u=i==0?scrwhere(col.Reg.beg,row1*gp_Cols):(k>?row1)*gp_Cols;
  135.         while(S->l==L) S++->ok=0; S--;
  136.         v=m?scrwhere(col.Reg.end,lastrow*gp_Cols):((S-Sl)*gp_Cols+S->nc);
  137.         u>?=row1*gp_Cols; v<?=lastrow*gp_Cols; u*=2; v*=2;
  138.         T=(char*)screen+1; for(j=u;j<v;j+=2) if(T[j]!=Red) T[j]=h;}
  139.     if(m) break;}
  140.     col.Reg.beg=mark(); col.Reg.end=mark();}
  141. Sl[lastrow].l=modeline; oldch=changed; emptydustbin();
  142. if(redrawinfo) redraw_info();
  143. if(cursor.c>=gp_Cols) {Moan=offscreen; cursor.c=gp_Cols-1;} gp_cursor(cursor);
  144. /*** if any change of window sizes, Sl[i].ok=0 on affected lines ***/
  145. /*** ditto for all lines of any buffer that I get rid of ***/ }
  146. /*----- display string s on screen line n (displayn = do not clear to eol) */
  147. int displayn(val T,int n,int c,int fc/*=White*/,int bc/*=Black*/){
  148. reg int i,j; short attr=Attrib(fc,bc); uns short*SL=Sl[n].sa;
  149. for(i=(j=T.n<?(gp_Cols-c))-1;i>=0;i--) SL[c+i]=sch(T.s[i],attr); Sl[n].ok=0;
  150. return j+c;} /* returns next free col */
  151. /*-----*/
  152. int displayn(char*s,int n,int c,int fc/*=White*/,int bc/*=Black*/){
  153. return displayn(val(s,strlen(s)),n,c,fc,bc);}
  154. /*-----*/
  155. void display(val T,int n,int c,int fc/*=White*/,int bc/*=Black*/){
  156. int i=displayn(T,n,c,fc,bc); gp_clear(n,i,gp_Cols-1);}
  157. /*-----*/
  158. void display(char*s,int n,int c,int fc/*=White*/,int bc/*=Black*/){
  159. int i=displayn(val(s,strlen(s)),n,c,fc,bc); gp_clear(n,i,gp_Cols-1);}
  160. /*----------*//* MOUSE */
  161. #include <dos.h>
  162. Mouse Jerry; Regs R;
  163. /*-----*/
  164. void Mouse::show(){R.x.ax=1; Int(0x33); visible=1;};
  165. void Mouse::hide(){R.x.ax=2; Int(0x33); visible=0;};
  166. void Mouse::read(){R.x.ax=3; Int(0x33); x=R.x.cx>>3; y=R.x.dx>>3;};
  167. void Mouse::move(int Y,int X){
  168.     R.x.ax=4; R.x.cx=X*8+4; R.x.dx=Y*8+4; Int(0x33); read();};
  169. void Mouse::range(int YE,int XE){
  170.     R.x.ax=7; R.x.cx=0; R.x.dx=XE*8-1; Int(0x33); xe=XE;
  171.     R.x.ax=8; R.x.cx=0; R.x.dx=YE*8-1; Int(0x33); ye=YE;}
  172. Mouse::~Mouse(){hide(); settrap(0,(void (*)(Regs *))(0));};
  173. void Mouse::operator=(mousestate&m){move(m.x,m.y);
  174.   if(m.visible) show(); else hide(); mc=m.mc; bd=m.bd; range(m.ye,m.xe);}
  175. /*-----*/
  176. void mousestate::operator=(Mouse&m){
  177. x=m.x; y=m.y; visible=m.visible; mc=m.mc; bd=m.bd; xe=m.xe; ye=m.ye;};
  178. /*-----*/
  179. /* Simulate a software interrupt from protected mode. Like int86() but calls
  180.    DPMI services and so doesn't need DOS extender, only a DPMI server. */
  181. int int86dpmi(int intno) {REGS r,s; Regs S; S=R;
  182. S.x.ss=S.x.sp=0;        /* DPMI server is to provide stack for interrupt call */
  183. S.x.flags=0;                         /* he likeliest forgot to zero the flags */
  184. /* I replaced the call of _go32_dpmi_simulate_int() by a copy of its body here*/
  185. r.h.bl=intno; r.h.bh=0; r.x.cx=0; r.x.di=(int)&S;
  186. if(intno==0x21 && S.x.ax==0x4b00) {                   /* call a child process */
  187.       r.x.ax=0xff0a; int86(0x21,&r,&s);}
  188. else {r.x.ax=0x0300; int86(0x31,&r,&s);}
  189. R=S; return R.d.eax;}
  190. /*-----*/
  191. Regs cb_regs; static _go32_dpmi_seginfo cb_info; /* for callback */
  192. /*-----*/
  193. void Mouse::settrap(uns int mask,void (*func)(Regs *)) {REGS r;
  194. /* This is tricky in protected-mode. We must allocate a real-mode wrapper
  195.    function which will be called by the mouse driver, and which in turn will
  196.    switch to protected-mode and call our protected-mode handler function. */
  197. if(!Jerry.nbuttons) return;
  198. if(!func) {Jerry.handlerInstalled=0; /* remove handler */
  199.     _go32_dpmi_free_real_mode_callback(&cb_info); R.x.dx=R.x.es=0;}
  200. else { /* Allocate real-mode call-back. Find real-mode address of handler */
  201.     cb_info.pm_offset=(uns long)func; Jerry.handlerInstalled=1;
  202.     if(_go32_dpmi_allocate_real_mode_callback_retf(&cb_info,&cb_regs)) return;
  203.     R.x.dx=cb_info.rm_offset; R.x.es=cb_info.rm_segment;}
  204. R.x.ax=12; R.x.cx=mask; int86dpmi(0x33);}
  205. /*-----*/
  206. void event(Regs*R){char events;
  207. events=R->x.ax; Jerry.buttons=R->x.bx&7; Jerry.x=R->x.cx/8; Jerry.y=R->x.dx/8;
  208. if(events&1&Jerry.mc) inject(-mousemove); /* mouse moved */
  209. #define J Jerry /* buttons pressed */
  210. if(events&0x02) {if(J.bd) inject(-lbuttond); J.ldx=J.x; J.ldy=J.y;}
  211. if(events&0x20) {if(J.bd) inject(-mbuttond); J.mdx=J.x; J.mdy=J.y;}
  212. if(events&0x08) {if(J.bd) inject(-rbuttond); J.rdx=J.x; J.rdy=J.y;}
  213. if(events&0x04) inject(-lbutton); /* buttons released */
  214. if(events&0x40) inject(-mbutton);
  215. if(events&0x10) inject(-rbutton);}
  216. #undef J
  217. /*-----*/
  218. void Mouse::setup() {_go32_dpmi_seginfo info;
  219. /* Check if a mouse is installed. If it is, then somebody
  220.    (the mouse driver) should have grabbed the 33h interrupt vector. */
  221. buttons=nbuttons=handlerInstalled=visible=0;
  222. /* if(_go32_dpmi_get_real_mode_interrupt_vector(0x33,&info)) return;
  223. if(!info.rm_segment) if(!info.rm_offset) return; /* exit if no mouse driver */
  224. R.x.ax=0; Int(0x33); /* Initialise mouse driver */
  225. if(!(R.x.ax&0xffff)) return; /* no mouse found */
  226. nbuttons=R.x.bx&0xff; move(0,0); mc=bd=0; hide(); range(gp_Cols,gp_Rows);}
  227. /*-----*/
  228. KF(mouse_mode) {if(!Jerry.mc) {B->olddot=B->dot; Jerry.mc=Jerry.bd=1;}
  229. else if(B->dot==B->olddot) Sl[B->lastrow].ok=Jerry.mc=Jerry.bd=0;
  230. else {B->Mark(1)=B->olddot; B->Mark(2)=B->dot;}}
  231. /*-----*/
  232. KF(setolddot) {B->olddot=B->dot;}
  233. /*-----*/
  234. KF(mouse_move) {int i,n,x=oldmx,y=oldmy; line*P;
  235. Z: if(!(n=Jerry.y-y)) if(x==Jerry.x) goto Y;
  236. if(B->longlines) if(Jerry.x>=gp_Cols) Jerry.move(Jerry.y,gp_Cols-1);
  237. if(B->longlines) godownpart(val(n,_int),val(Jerry.x,_int));
  238. else {
  239.     if(n>=0) {for(i=0;i<n;i++) if(P=B->dot.r->next) B->dot.r=P; else break;}
  240.     else     {for(i=0;i>n;i--) if(P=B->dot.r->prev) B->dot.r=P; else break;}
  241.     B->dot.c=B->dot.r->from_tabexp(Jerry.x); y+=i;}
  242. if(Jerry.buttons&1) (B->olddot-B->dot).color(White,Magenta);
  243. B->dotcc=B->dotcc2=-1; B->display(); x=Jerry.x; P=B->dot.r;
  244. if(P==B->text.next?:P==B->text.prev) Jerry.move(y,x); else y=Jerry.y;
  245. Y: i=getkey(); if(i==-mousemove) goto Z; else nextch=i;}
  246.